// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build linux&&（mips | | mipsle）

package syscall

import "unsafe"

const _SYS_setgroups = SYS_SETGROUPS

func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)

// sys Dup2（oldfd int，newfd int）（error error）
// sysnb EpollCreate（size int）（fd int，error error）
// sysnb Geteuid（）（euid int）
// sysnb Getgid（）（gid int）
// sysnb Getuid（）（uid int）
// SYS Lchown
// sys Pread（fd int，p[]byte，offset int64）（n int，error error）=sys_PREAD64 
// sys Pwrite（fd int，p[]byte，offset int64）（n int，error error）=sys PWRITE64 
// sys Renameat（olddirfd int，oldpath string，newdirfd int，newpath string）（error）
// sys Select（nfd int，r*FdSet，w*FdSet，e*FdSet，Timeval，Timeval）（n int，error）=SYS_uunewselect 
// SYS sendfile（outd int，infd int，offset*int64，count int）（writed int，error error）=SYS_usendfile64 
// SYS Setfsgid（gid int）（error error）
// SYS Shutdown（fd int，how int）（error）
// SYS splication（rfd int，roff*int64，wfd int，woff*int（n int，error error）

// sys-SyncFileRange（fd int，off int64，n int64，flags int）（error error）
// sys Truncate（path string，length int64）（error error）=sys TRUNCATE64 
// sys Ustat（dev int，ubuf*ustatt）（error）
// sys accept（s int，rsa*RawSockaddrAny，addren Socklen*（fd int，error）
// sys bind（s int，addr unsafe.Pointer，addrlen _Socklen）（error）
// sys connect（s int，level int，name int，val unsafe.Pointer，vallen*_Socklen）（错误）
// sys setsockopt（s int，level int，name int，val unsafe.Pointer，vallen uintptpr）（错误）
// sysnb socket（域int，类型int，proto int）（fd int，错误）
// sysnb socketpair（域int，类型int，proto int，fd 32）（错误）
// sysnb getsockname（fd int，rsa*RawSockaddrAny，addrlen*_Socklen）（error）
// sys recvfrom（fd int，p[]byte，flags int，from*RawSockaddrAny，fromlen*_Socklen）（n int，error）
// sys sendto（s int，buf[]byte，flags int，flags int，to unsafe.Pointer，abdrop，addrlen）
// sys sendmsg（s int，msg*Msghdr，flags int）（n int，error error）

// sysnb InotifyInit（）（fd int，error error）
// sys Iopl（level int）（error error error error）

// sys fd int，path string，times*Timeval（error error）
// sysnb Gettimeofday（tv*Timeval）（error error）
// sysnb Time（t*Time_t）（tt Time_t，error error）
// sys Utime（path string，buf*Utimbuf）（error）
// sys utimes path string，times*[2]Timeval）（error）

// sys Lstat（fd int，stat*stat_t）（err error）=SYS_FSTAT64 
// SYS stat（path string，stat*stat_t）（error error）=SYS STAT64 
// SYS EpollWait（epfd int，events[]epolletent，msec int）（n int，error error）

func Fstatfs(fd int, buf *Statfs_t) (err error) {
	_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = errnoErr(e)
	}
	return
}

func Statfs(path string, buf *Statfs_t) (err error) {
	p, err := BytePtrFromString(path)
	if err != nil {
		return err
	}
	_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(p)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
	if e != 0 {
		err = errnoErr(e)
	}
	return
}

func Seek(fd int, offset int64, whence int) (off int64, err error) {
	_, _, e := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offset>>32), uintptr(offset), uintptr(unsafe.Pointer(&off)), uintptr(whence), 0)
	if e != 0 {
		err = errnoErr(e)
	}
	return
}

func setTimespec(sec, nsec int64) Timespec {
	return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
}

func setTimeval(sec, usec int64) Timeval {
	return Timeval{Sec: int32(sec), Usec: int32(usec)}
}


func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
	page := uintptr(offset / 4096)
	if offset != int64(page)*4096 {
		return 0, EINVAL
	}
	return mmap2(addr, length, prot, flags, fd, page)
}

const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)

type rlimit32 struct {
	Cur uint32
	Max uint32
}


func Getrlimit(resource int, rlim *Rlimit) (err error) {
	err = prlimit(0, resource, nil, rlim)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	err = getrlimit(resource, &rl)
	if err != nil {
		return
	}

	if rl.Cur == rlimInf32 {
		rlim.Cur = rlimInf64
	} else {
		rlim.Cur = uint64(rl.Cur)
	}

	if rl.Max == rlimInf32 {
		rlim.Max = rlimInf64
	} else {
		rlim.Max = uint64(rl.Max)
	}
	return
}

// sysnb setrlimit（资源int，rlim*rlimit32）（错误）=SYS_setrlimit 

func Setrlimit(resource int, rlim *Rlimit) (err error) {
	err = prlimit(0, resource, rlim, nil)
	if err != ENOSYS {
		return err
	}

	rl := rlimit32{}
	if rlim.Cur == rlimInf64 {
		rl.Cur = rlimInf32
	} else if rlim.Cur < uint64(rlimInf32) {
		rl.Cur = uint32(rlim.Cur)
	} else {
		return EINVAL
	}
	if rlim.Max == rlimInf64 {
		rl.Max = rlimInf32
	} else if rlim.Max < uint64(rlimInf32) {
		rl.Max = uint32(rlim.Max)
	} else {
		return EINVAL
	}

	return setrlimit(resource, &rl)
}

func (r *PtraceRegs) PC() uint64 { return uint64(r.Regs[64]) }

func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = uint32(pc) }

func (iov *Iovec) SetLen(length int) {
	iov.Len = uint32(length)
}

func (msghdr *Msghdr) SetControllen(length int) {
	msghdr.Controllen = uint32(length)
}

func (cmsg *Cmsghdr) SetLen(length int) {
	cmsg.Len = uint32(length)
}

func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno)
